home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
CLLZW.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-11
|
23KB
|
820 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: class.cpp
// Title: C++ Class Libraries
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
// This module contains code for the class CL_LZW.
// This is a very simplified LZW-type compressor/expander. It handles binary
// files but it always outputs 1.5 byte codes. This means that as a worst
// case, a buffer can end up being 1.5 times it's original size.
//
// Some of the routines in this module have been 'unrolled' to speed
// things up. Be very careful when changing code since this module was
// profiled and hand optimized (and it is still slow!).
//
// This class is very large, it should be allocated dynamically.
//
// The code in this module may be written in C++ or C.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
//
//----------------------------------------------------------------------------
#include <class.hpp>
//----------------------------------------------------------------------------
// Constants
//----------------------------------------------------------------------------
#define LZW_BUF1 (8192)
#define LZW_BUF2 (LZW_BUF1+LZW_BUF1/2)
#if OS_UNIX
# define LF "\n"
#else
# define LF "\r\n"
#endif
#define CTRLZ "\x1A"
#define LZWVER (0x0100)
#define LZWID (0x12348765L)
static CHAR szHeaderFormat[] = // File header format text
"Compressed File v%d.%02d" LF
"%s" LF
"Created %2d:%02d:%02d %2d/%02d/%4d" LF
CTRLZ;
typedef struct _LZWHDR // Configuration file header
{
CHAR szText[256]; // Header description
LONG lId; // Identifier word
USHORT usVer; // File version
CRC crc; // CRC of file
TIMET timet; // Time file was created
USHORT usAttrib; // File attributes
BYTE bUnused[256 - 4 - 2 - 4 - 4 - 2];
} LZWHDR;
BASETYPE(LZWHDR);
//----------------------------------------------------------------------------
// Description: Default constructor
// Parameters:
// Returns:
//----------------------------------------------------------------------------
FN_M CL_LZW::CL_LZW()
{
CL_LZW::Initialize(CL_INIT_CLASS);
}
//----------------------------------------------------------------------------
// Description: Copy constructor
// Parameters: rccl_lzw Reference to object to copy.
// Returns:
//----------------------------------------------------------------------------
FN_M CL_LZW::CL_LZW(RCCL_LZW rccl_lzw)
{
CL_LZW::Initialize(CL_INIT_CLASS);
*this = rccl_lzw;
}
//----------------------------------------------------------------------------
// Description: Destructor
// Parameters:
// Returns:
//----------------------------------------------------------------------------
FN_M CL_LZW::~CL_LZW()
{
CL_LZW::Destroy(FALSE);
}
//----------------------------------------------------------------------------
// Description: Add a symbol to the table. Ignore if table is full
// Parameters: sSym1 Symbols
// sSym2 Symbols
// Returns:
//----------------------------------------------------------------------------
VOID FN_M CL_LZW::Add(SHORT sSym1, SHORT sSym2)
{
if (cSym < LZW_SYMBOLS)
{
asym[cSym].cLen = asym[sSym1].cLen + asym[sSym2].cLen;
asym[cSym].sSym[0] = sSym1;
asym[cSym].sSym[1] = sSym2;
sSym1 = (SHORT)asym[sSym1].sFirst;
asym[cSym].sFirst = (BYTE)sSym1;
asym[cSym].sNext = asym[sSym1].sNext;
asym[sSym1].sNext = (SHORT)cSym;
cSym++;
if (cSym == 2048)
cBits = 12;
else if (cSym == 1024)
cBits = 11;
else if (cSym == 512)
cBits = 10;
}
return ;
}
//----------------------------------------------------------------------------
// Description: Encode a buffer.
// Parameters: _pbIn Pointer to input buffer
// _cbIn Size of input buffer
// _pbOut Pointer to output buffer
// _cbOut Size of output buffer
// Returns: Size of encoded buffer or 0
//----------------------------------------------------------------------------
SIZET FN_M CL_LZW::Decode(PBYTE _pbIn, SIZET _cbIn, PBYTE _pbOut, SIZET _cbOut)
{
Assert(_pbIn && _cbIn);
Assert(_pbOut && _cbOut);
CL_LZW::Initialize();
pbIn = _pbIn;
cbIn = _cbIn;
pbOut = _pbOut;
cbOut = _cbOut;
SHORT sPrev = -1;
SHORT sSym;
while ((sSym = Read()) != -1)
{
if (sSym < 256) // An ascii symbol
{
if (!cbOut)
return 0;
*pbOut = (BYTE)sSym;
pbOut++;
cbOut--;
cbData++;
}
else if (!Expand(sSym)) // Expand the hard way
return 0;
if (sPrev >= 0) // Add new symbol to table
Add(sPrev, sSym);
sPrev = sSym; // Save current symbol
}
return cbData;
}
//----------------------------------------------------------------------------
// Description: Decode a file.
// Parameters: pcszOut Output file name.
// pcszIn Input file name.
// If null, a default file name is created.
// Default is NULL.
// pfnlzw Callback function to monitor progress
// Returns: Size of encoded buffer or 0
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::DecodeFile(PCSZ pcszOut, PCSZ pcszIn, PFNLZW pfnlzw)
{
CHAR szIn[MAX_PATH];
FLAG16 fs1 = FL_CREATE|FL_TRUNCATE|FL_READWRITE|FL_DENYREADWRITE|FL_BINARY;
FLAG16 fs2 = FL_OPEN|FL_READWRITE|FL_DENYREADWRITE|FL_BINARY;
FPOS fsize = 0;
HF hf1 = -1, hf2 = -1;
PBYTE pbBuf1 = NULL, pbBuf2 = NULL;
BOOL fResult = FALSE;
LONG lTotal = 0;
LZWHDR lzwhdr;
CRC crc = 0;
BS_FINFO finfo;
Assert(pcszOut);
if (pcszIn == NULL)
{
strcpy(szIn, pcszOut);
pcszIn = szIn;
FnameAppendExt(szIn, "$$$", TRUE);
}
pbBuf1 = (PBYTE)MemAlloc(LZW_BUF1);
pbBuf2 = (PBYTE)MemAlloc(LZW_BUF1);
if (pbBuf1 == NULL || pbBuf2 == NULL)
{
ErrorNoMem();
goto ERROR_EXIT;
}
if (!FileOpen(&hf1, pcszOut, fs1, NULL))
goto ERROR_EXIT;
if (!FileOpen(&hf2, pcszIn, fs2, NULL))
goto ERROR_EXIT;
fsize = FileGetSize(hf2);
if (fsize <= sizeof(LZWHDR))
goto ERROR_EXIT;
if (!FileRead(hf2, &lzwhdr, sizeof(lzwhdr), 0))
goto ERROR_EXIT;
fsize -= (FPOS)sizeof(LZWHDR);
if (lzwhdr.lId != LZWID || lzwhdr.usVer != LZWVER)
{
Error("Invalid compressed file format.");
goto ERROR_EXIT;
}
FileSetPos(hf1, 0, FL_BEGIN);
FileSetPos(hf2, sizeof(LZWHDR), FL_BEGIN);
lTotal = fsize;
while (fsize)
{
if (pfnlzw)
pfnlzw(lTotal - (long)fsize, lTotal);
if (fsize < sizeof(SIZET))
goto ERROR_EXIT;
SIZET cRead;
if (!FileRead(hf2, (PBYTE)&cRead, sizeof(cRead), -1))
goto ERROR_EXIT;
fsize -= (FPOS)sizeof(cRead);
SIZET cActual = cRead & 0x7FFF;
if (fsize < (FPOS)cActual || cActual > LZW_BUF1)
goto ERROR_EXIT;
if (!FileRead(hf2, pbBuf2, cActual, -1))
goto ERROR_EXIT;
fsize -= (FPOS)cActual;
if (cRead & 0x8000)
{
crc = CrcCalcAppend(pbBuf2, cActual, crc);
if (!FileWrite(hf1, pbBuf2, cActual, -1))
goto ERROR_EXIT;
}
else
{
SIZET cDecode;
cDecode = Decode(pbBuf2, cActual, pbBuf1, LZW_BUF1);
if (!cDecode || cDecode < cRead || cDecode > LZW_BUF1)
goto ERROR_EXIT;
crc = CrcCalcAppend(pbBuf1, cDecode, crc);
if (!FileWrite(hf1, pbBuf1, cDecode, -1))
goto ERROR_EXIT;
}
}
if (crc != lzwhdr.crc)
{
Error("Error in compressed file.\nInvalid CRC.");
goto ERROR_EXIT;
}
FileClose(hf1);
hf1 = -1;
memset(&finfo, 0, sizeof(finfo));
finfo.timet = lzwhdr.timet;
finfo.usAttrib = lzwhdr.usAttrib;
if (!FinfoSet(pcszOut, &finfo))
goto ERROR_EXIT;
fResult = TRUE;
ERROR_EXIT:
if (pfnlzw)
pfnlzw(lTotal - (long)fsize, lTotal);
if (hf1 >= 0)
FileClose(hf1);
if (hf2 >= 0)
FileClose(hf2);
if (pbBuf1)
MemFree(pbBuf1);
if (pbBuf2)
MemFree(pbBuf2);
return fResult;
}
//----------------------------------------------------------------------------
// Description: Destroy object. Free any resources used by object.
// Normally called by destructor.
// Should allow multiple calls from various classes.
// A class should almost always re-init its variables when
// it is destroyed to prevent accidents.
// Parameters: fDestroyAll Destroy parents also?
// Default is TRUE.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Destroy(BOOL fDestroyAll)
{
Initialize(CL_INIT_CLASS_VARS);
if (fDestroyAll) // Destroy parent.
CL_LZW_PARENT::Destroy(fDestroyAll);
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Encode a buffer.
// Parameters: _pbIn Pointer to input buffer
// _cbIn Size of input buffer
// _pbOut Pointer to output buffer
// _cbOut Size of output buffer
// Returns: Size of encoded buffer or 0
//----------------------------------------------------------------------------
SIZET FN_M CL_LZW::Encode(PBYTE _pbIn, SIZET _cbIn, PBYTE _pbOut, SIZET _cbOut)
{
Assert(_pbIn && _cbIn);
Assert(_pbOut && _cbOut);
Assert(_cbOut >= ((_cbIn * 3) + 1) / 2);
Initialize();
pbIn = _pbIn;
cbIn = _cbIn;
pbOut = _pbOut;
cbOut = _cbOut;
SHORT sPrev = -1;
SHORT sSym;
while (cbIn)
{
sSym = (SHORT)*pbIn; // Assume ASCII symbol
SHORT sNext = asym[sSym].sNext;
for (; sNext >= 0; sNext = asym[sNext].sNext)
if (asym[sNext].cLen <= cbIn
&& asym[sNext].cLen > asym[sSym].cLen
&& asym[sNext].sFirst == *pbIn
&& IsMatch(pbIn, sNext))
sSym = sNext;
if (!Write(sSym)) // Write symbol
return 0;
if (sPrev >= 0) // Add new symbol to table
Add(sPrev, sSym);
sPrev = sSym; // Save current symbol
cbIn -= asym[sSym].cLen; // Move to next byte
pbIn += asym[sSym].cLen;
}
return cbData;
}
//----------------------------------------------------------------------------
// Description: Encode a file.
// Parameters: pcszIn Input file name.
// pcszOut Output file name.
// If null, a default file name is created.
// Default is NULL.
// pfnlzw Callback function to monitor progress
// Returns: Size of encoded buffer or 0
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::EncodeFile(PCSZ pcszIn, PCSZ pcszOut, PFNLZW pfnlzw)
{
CHAR szOut[MAX_PATH];
FLAG16 fs1 = FL_OPEN|FL_READWRITE|FL_DENYREADWRITE|FL_BINARY;
FLAG16 fs2 = FL_CREATE|FL_TRUNCATE|FL_READWRITE|FL_DENYREADWRITE|FL_BINARY;
FPOS fsize = 0;
HF hf1 = -1, hf2 = -1;
PBYTE pbBuf1 = NULL, pbBuf2 = NULL;
BOOL fResult = FALSE;
LONG lTotal = 0;
LZWHDR lzwhdr;
time_t now = time(NULL);
struct tm *tm = localtime(&now);
BS_FINFO finfo;
Assert(pcszIn);
if (!FnameIsFile(pcszIn))
return Error("Input file not found.");
Assert(sizeof(LZWHDR) == 512);
if (pcszOut == NULL)
{
strcpy(szOut, pcszIn);
pcszOut = szOut;
FnameAppendExt(szOut, "$$$", TRUE);
}
pbBuf1 = (PBYTE)MemAlloc(LZW_BUF1);
pbBuf2 = (PBYTE)MemAlloc(LZW_BUF2);
if (pbBuf1 == NULL || pbBuf2 == NULL)
{
ErrorNoMem();
goto ERROR_EXIT;
}
if (!FinfoGet(pcszIn, &finfo))
goto ERROR_EXIT;
if (!FileOpen(&hf1, pcszIn, fs1, NULL))
goto ERROR_EXIT;
fsize = FileGetSize(hf1);
if (fsize <= 0)
goto ERROR_EXIT;
if (!FileOpen(&hf2, pcszOut, fs2, NULL))
goto ERROR_EXIT;
// Write header
memset(&lzwhdr, 0, sizeof(lzwhdr));
sprintf(lzwhdr.szText,
szHeaderFormat,
(int)((LZWVER >> 8) & 0x00FF),
(int)(LZWVER & 0x00FF),
CfgGet(CFG_COPYRIGHT),
tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
lzwhdr.lId = LZWID;
lzwhdr.usVer = LZWVER;
lzwhdr.crc = 0;
lzwhdr.timet = finfo.timet;
lzwhdr.usAttrib = finfo.usAttrib;
if (!FileWrite(hf2, &lzwhdr, sizeof(lzwhdr), 0))
goto ERROR_EXIT;
FileSetPos(hf1, 0, FL_BEGIN);
FileSetPos(hf2, sizeof(LZWHDR), FL_BEGIN);
lTotal = fsize;
while (fsize)
{
if (pfnlzw)
pfnlzw(lTotal - (long)fsize, lTotal);
SIZET cRead = (SIZET)MIN((FPOS)LZW_BUF1, fsize);
if (!FileRead(hf1, pbBuf1, cRead, -1))
goto ERROR_EXIT;
lzwhdr.crc = CrcCalcAppend(pbBuf1, cRead, lzwhdr.crc);
SIZET cEncode;
cEncode = Encode(pbBuf1, cRead, pbBuf2, LZW_BUF2);
if (!cEncode)
goto ERROR_EXIT;
if (cEncode >= cRead)
cEncode = 0x8000|cRead;
if (!FileWrite(hf2, (PBYTE)&cEncode, sizeof(cEncode), -1))
goto ERROR_EXIT;
if (cEncode >= cRead)
{
if (!FileWrite(hf2, pbBuf1, cRead, -1))
goto ERROR_EXIT;
}
else
{
if (!FileWrite(hf2, pbBuf2, cEncode, -1))
goto ERROR_EXIT;
}
fsize -= (FPOS)cRead;
} // Write updated CRC code
if (!FileWrite(hf2, &lzwhdr, sizeof(lzwhdr), 0))
goto ERROR_EXIT;
fResult = TRUE;
ERROR_EXIT:
if (pfnlzw)
pfnlzw(lTotal - (long)fsize, lTotal);
if (hf1 >= 0)
FileClose(hf1);
if (hf2 >= 0)
FileClose(hf2);
if (pbBuf1)
MemFree(pbBuf1);
if (pbBuf2)
MemFree(pbBuf2);
return fResult;
}
//----------------------------------------------------------------------------
// Description: Expand a symbol into a string
// This function is recursive!!
// Parameters: sSym Symbol
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Expand(SHORT sSym)
{
SHORT sSym1 = asym[sSym].sSym[0]; // Expand sub-strings (recurse)
SHORT sSym2 = asym[sSym].sSym[1];
if (sSym1 < 256) // An ascii symbol
{
if (!cbOut)
return FALSE;
*pbOut = (BYTE)sSym1;
pbOut++;
cbOut--;
cbData++;
}
else if (!Expand(sSym1))
return FALSE;
if (sSym2 < 256) // An ascii symbol
{
if (!cbOut)
return FALSE;
*pbOut = (BYTE)sSym2;
pbOut++;
cbOut--;
cbData++;
}
else if (!Expand(sSym2))
return FALSE;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Initialize object.
// Normally called by constructor.
// Should allow multiple calls from various classes.
// Parameters: sInit Initialization code. May be one of the following:
// CL_INIT_CLASS Reset class variables and
// and dynamic allocations for
// this class only.
// CL_INIT_CLASS_VARS Reset class variables for
// this class only.
// CL_INIT_VARS Reset class variables for
// this class only.
// CL_INIT_ALL Initialize class and all
// parent class, including
// dynamic memory allocation.
// Default is CL_INIT_ALL
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Initialize(SHORT sInit)
{
if (sInit == CL_INIT_VARS || sInit == CL_INIT_ALL)
CL_LZW_PARENT::Initialize(sInit);
memset(asym, 0, sizeof(asym));
for (cSym = 0; cSym < 256; ++cSym) // Add ascii symbols
{
asym[cSym].cLen = 1;
asym[cSym].sSym[0] = (SHORT)cSym;
asym[cSym].sFirst = (BYTE)cSym;
asym[cSym].sNext = -1;
}
cbData = 0;
cBitsLeft = 8;
cBits = 9;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Check if a string matches the specified symbol
// This function is recursive!!
// Parameters: pb String
// sSym Symbol
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::IsMatch(PBYTE pb, SHORT sSym)
{
SHORT sSym1 = asym[sSym].sSym[0]; // Match sub-strings (recurse)
SHORT sSym2 = asym[sSym].sSym[1];
if (sSym1 < 256) // This routine has been unrolled
{ // for speed
if (sSym2 < 256)
{
return pb[0] == (BYTE)sSym1 && pb[1] == (BYTE)sSym2;
}
else
{
return pb[0] == (BYTE)sSym1
&& pb[1] == (BYTE)asym[sSym2].sFirst
&& IsMatch(pb + 1, sSym2);
}
}
else
{
if (pb[0] != (BYTE)asym[sSym1].sFirst || !IsMatch(pb, sSym1))
return FALSE;
PBYTE pb2 = pb + asym[sSym1].cLen;
if (sSym2 < 256)
{
return pb2[0] == (BYTE)sSym2;
}
else
{
return pb2[0] == (BYTE)asym[sSym2].sFirst
&& IsMatch(pb2, sSym2);
}
}
}
//----------------------------------------------------------------------------
// Description: Assignment operator
// NOTE: Don't copy object into self
// Parameters: rccl_lzw Reference to right value.
// Returns: Reference to new object.
//----------------------------------------------------------------------------
RCCL_LZW FN_M CL_LZW::operator=(RCCL_LZW rccl_lzw)
{
if (this != &rccl_lzw)
{
Invalid("CL_LZW::operator=");
}
return (RCCL_LZW)*this;
}
//----------------------------------------------------------------------------
// Description: Read a symbol
// Parameters:
// Returns: Symbol or -1 for end of buffer
//----------------------------------------------------------------------------
SHORT FN_M CL_LZW::Read()
{
SHORT sSym;
SIZET cBitsNeeded = cBits;
if (cBitsLeft == 8) // Initialize byte for output
{
if (!cbIn)
return -1;
cbIn--;
}
sSym = *pbIn++;
cBitsNeeded -= cBitsLeft;
if (cBitsNeeded > 8)
{
if (!cbIn)
return -1;
cbIn--;
sSym <<= 8;
sSym |= *pbIn++;
cBitsNeeded -= 8;
}
if (!cbIn)
return -1;
cbIn--;
sSym <<= cBitsNeeded;
if (cBitsNeeded < 8)
{
cBitsLeft = 8 - cBitsNeeded;
sSym |= (SHORT)(*pbIn >> cBitsLeft);
}
else // Exactly 8 bits left
{
sSym |= *pbIn++;
cBitsLeft = 8;
}
return (SHORT)(sSym & (0xFFFF >> (16 - cBits)));
}
//----------------------------------------------------------------------------
// Description: Retrieve object from persistent storage
// Parameters: pcsz Name of object.
// pcszSub Sub-name of object.
// The first character of the name should be '~'.
// If NULL, no sub name is available.
// Default is NULL
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Retrieve(PCSZ pcsz, PCSZ pcszSub)
{
NOTUSED(pcsz);
NOTUSED(pcszSub);
Invalid("CL_LZW::Retrieve");
return FALSE;
}
//----------------------------------------------------------------------------
// Description: Store object to persistent storage
// Parameters: pcsz Name of object.
// pcszSub Sub-name of object.
// The first character of the name should be '~'.
// If NULL, no sub name is available.
// Default is NULL
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Store(PCSZ pcsz, PCSZ pcszSub)
{
NOTUSED(pcsz);
NOTUSED(pcszSub);
Invalid("CL_LZW::Store");
return FALSE;
}
//----------------------------------------------------------------------------
// Description: Write a symbol
// Parameters: sSym Symbol
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M CL_LZW::Write(SHORT sSym)
{
SIZET cBitsNeeded = cBits;
if (cBitsLeft == 8) // Initialize byte for output
{
cbData++;
if (cbData > cbOut)
return FALSE;
*pbOut = 0;
} // Out remainder of current byte
*pbOut |= (sSym >> (cBitsNeeded - cBitsLeft));
cBitsNeeded -= cBitsLeft;
pbOut++; // Move to next byte
if (cBitsNeeded > 8)
{
cbData++;
if (cbData > cbOut)
return FALSE;
*pbOut = ((BYTE)sSym >> (cBitsNeeded - 8));
pbOut++;
cBitsNeeded -= 8;
}
cbData++;
if (cbData > cbOut)
return FALSE;
*pbOut = (BYTE)sSym;
if (cBitsNeeded < 8)
{
cBitsLeft = 8 - cBitsNeeded;
*pbOut <<= cBitsLeft;
}
else // Exactly 8 bits left
{
pbOut++;
cBitsLeft = 8;
}
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Run standard test suite on object.
// Parameters: sTest Test to run.
// If 0, run default tests.
// Default is 0.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
#if COMPILE_DEBUG
BOOL FN_M CL_LZW::Test(SHORT sTest)
{
#if COMPILE_TEST
static CL_LZW _FAR_ cl_lzw;
static BYTE bDecode[4096];
static BYTE bEncode[4096 + (4096/2)];
static PCSZ apcsz[] =
{
"ABCABC",
"A",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"ABABABABABABABABABABABAB",
NULL
};
if (sTest == 0)
for (SIZET i = 0; apcsz[i]; ++i)
{
Output("[%s]\n", apcsz[i]);
Output(" Input: %d\n", strlen(apcsz[i]) + 1);
SIZET cbEncode = cl_lzw.Encode((PBYTE)apcsz[i], strlen(apcsz[i]) + 1,
bEncode, sizeof(bEncode));
if (!cbEncode)
return FALSE;
Output(" Output: %d\n", cbEncode);
SIZET cbDecode = cl_lzw.Decode(bEncode, cbEncode, bDecode,
sizeof(bDecode));
if (cbDecode != strlen(apcsz[i]) + 1
|| strcmp((PSZ)bDecode, apcsz[i]) != 0)
return FALSE;
}
if (sTest == 1)
{
PCSZ pcszFile = "test.dat";
if (!FnameIsFile(pcszFile))
{
return _Error("Could not find file '%s'.", pcszFile);
}
Output("Encoding...this may take several minutes...\n");
if (!cl_lzw.EncodeFile(pcszFile))
return FALSE;
}
if (sTest == 2)
{
Output("Decoding...\n");
if (!cl_lzw.DecodeFile("test.out"))
return FALSE;
}
return TRUE;
#else
NOTUSED(sTest);
return TRUE;
#endif
}
#endif
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------